<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>js类之继承super</title>
</head>
<body>
  <ul>
    <li>super可在子类的constructor中调用完成属性继承(一定要调用)，同时也能完成父类同名方法的调用</li>
    <li>如果子类构造函数存在则一定要使用super调用父类构造函数，同时this必须在super之后调用(防止父类覆盖子类成员)，但子类可缺省构造函数(不建议)</li>
    <li>如果子类有同名方法，则子类对象将优先调用自身的方法，使用super.xxx()调用父类同名方法</li>
    <li>super的本质就是子类对象的原型(__proto__)指向父类对象，并使用this.__proto__.xxx.call(this)完成同名方法调用</li>
    <li>通过修改原型指向完成继承只适用于两层继承关系之间同名方法调用，对于多重继承使用super.xxx()完成同名方法调用</li>
  </ul>
  <script>
    console.log('****************在class中使用super****************')
    {
      class User {
        constructor(name, age) {
          this.name = name
          this.age = age
        }
        show() {
          console.log(`${this.name} is ${this.age} years old.`)
        }
      }
      class Admin extends User {
        // 可缺省，但不建议
        // constructor(name, age) {
        //   super(name, age);
        // }
        show() {
          super.show()
          console.log('admin.show')
        }
      }
      console.dir(Admin)                        // class Admin
      const admin = new Admin('Miracle', 35)
      console.log(admin)                        // Admin {name: "Miracle", age: 35}
      admin.show()                              // Miracle is 35 years old. admin.show
    }
    console.log('****************super原理分析****************')
    {
      const user = {
        show() {
          console.log(`${this.name} is ${this.age} years old.`)
        }
      }
      const admin = {
        __proto__: user,
        name: 'Miracle',
        age: 35,
        show() {
          // this.show()                        // 此时调用自己，导致死循环
          // this.__proto__.show()              // 此时调用父类show但this是指向父类的
          this.__proto__.show.call(this)        // 此时一定要使用call将子类对象传入到父类同名方法
          console.log('admin.show')
        }
      }
      console.log(admin)                        // {name: "Miracle", age: 35, show: ƒ}
      admin.show()                              // Miracle is 35 years old. admin.show
    }
    console.log('****************super多重继承****************')
    {
      const common = {
        show() {
          console.log(`${this.name} is ${this.age} years old.`)
        }
      }
      const user = {
        __proto__: common,
        show() {
          // this.__proto__.show.call(this)    // 此时原型攀升到common, 但this.__proto__仍然是user，导致死循环
          super.show()
          console.log('user.show')
        }
      }
      const admin = {
        __proto__: user,
        name: 'Miracle',
        age: 35,
        show() {
          // this.show()                        // 此时调用自己，导致死循环
          // this.__proto__.show()              // 此时调用父类show但this是指向父类的
          // this.__proto__.show.call(this)     // 此时一定要使用call将子类对象传入到父类同名方法
          super.show()
          console.log('admin.show')
        }
      }
      console.log(admin)                        // {name: "Miracle", age: 35, show: ƒ}
      admin.show()                              // Miracle is 35 years old. user.show. admin.show
    }
  </script>
</body>
</html>